package com.dyy.thread;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author 小白丁
 * @Date 2021/2/24 23:30
 * @Version 1.0
 * @Description 线程池在构建的时候，含有三个重要的变量，线程池核心执行数量，线程池最大的数量，线程池的队列数量
 * 当线程池的最大数量加上线程池的队列数量已经满了之后，线程池需要对新入线程池中的任务进行拒绝处理，线程池本身有一个拒绝策略的捕获类
 * 线程池的拒绝策略RejectedExecutionHandle一共分为四种，包括
 * 1：调用者执行（CallerRunsPolicy），当线程池满了以后，由调用者进行任务执行
 * 2：直接拒绝（AbortPolicy），并报错 RejectedExecutionException，线程池默认拒绝策略，需要对异常进行拦截，否者会影响当前任务的执行
 * 3：直接丢弃（DiscardPolicy），丢弃，不做处理
 * 4：丢弃队列中最久的任务（DiscardOldestPolicy），丢弃掉线程队列中最老的任务
 */
public class ThreadPoolRejectHandler {

    private int coreSize = 5;
    private int maxPoolSize = 10;
    private int keepAlive = 5;
    BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(10);

    /**
     * 直接拒绝（AbortPolicy），并报错 RejectedExecutionException，线程池默认拒绝策略，需要对异常进行拦截，否者会影响当前任务的执行
     */
    private void abortPolicy() {
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, maxPoolSize, keepAlive, TimeUnit.SECONDS, queue,
            handler);
        for (int i = 0; i < 100; i++) {
            try {
                executor.execute(new Thread(() -> System.out.println(Thread.currentThread()
                    .getName() + " is running")));
            } catch (Exception e) {
                System.out.println("线程池已满，不能继续执行了");
            }
        }
    }

    /**
     * 直接拒绝（AbortPolicy），并报错 RejectedExecutionException，线程池默认拒绝策略，不拦截，主线程异常
     */
    private void abortPolicyWithCatch() {
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, maxPoolSize, keepAlive, TimeUnit.SECONDS, queue,
            handler);
        for (int i = 0; i < 100; i++) {
            executor.execute(new Thread(() -> System.out.println(Thread.currentThread()
                .getName() + " is running")));
        }
    }

    /**
     * 调用者执行（CallerRunsPolicy），当线程池满了以后，由调用者进行任务执行
     */
    private void callerRunPolicy() {
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, maxPoolSize, keepAlive, TimeUnit.SECONDS, queue,
            handler);
        for (int i = 0; i < 100; i++) {
            executor.execute(new Thread(() -> System.out.println(Thread.currentThread()
                .getName() + " is running")));
        }
    }

    /**
     * 直接丢弃（DiscardPolicy），丢弃，不做处理
     */
    private void discardPolicy() {
        RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, maxPoolSize, keepAlive, TimeUnit.SECONDS, queue,
            handler);
        for (int i = 0; i < 100; i++) {
            executor.execute(new Thread(() -> System.out.println(Thread.currentThread()
                .getName() + " is running ")));
        }
    }

    /**
     * 丢弃队列中最久的任务（DiscardOldestPolicy），丢弃掉线程队列中最老的任务
     */
    private void discardOldPolicy() {
        RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, maxPoolSize, keepAlive, TimeUnit.SECONDS, queue,
            handler);

        for (int i = 0; i < 100; i++) {
            executor.execute(new Thread(() -> System.out.println(Thread.currentThread()
                .getName() + " is running ")));
        }
    }

    public static void main(String[] args) {
        ThreadPoolRejectHandler handler = new ThreadPoolRejectHandler();
        System.out.println("默认的拒绝策略");
        handler.abortPolicy();
        System.out.println("调用者执行");
        handler.callerRunPolicy();
        System.out.println("丢弃");
        handler.discardPolicy();
        System.out.println("丢弃队列中最久的任务");
        handler.discardOldPolicy();
        System.out.println("默认拒绝，不拦截异常");
        handler.abortPolicyWithCatch();
    }

}
